/*
VED.dom = {};

VED.dom.domObject = new Class({
   getPrivate: function() {
      var priv;

      // Get the main private object from the custom data. Create it if not defined.
      if( !( priv = this.getCustomData( '_' ) ) )
         this.setCustomData( '_', ( priv = {} ) );

      return priv;
   },

});

(function(){

var customData = {};

VED.addEvent( 'reset', function() {
   customData = {};
});

VED.dom.domObject.implement({

   equals: function( object ) {
      var $this = ( typeof this.$node === 'undefined' ) ? this : this.$node;

		// Try/Catch to avoid IE permission error when object is from different document.
		try {
			return ( object && object === $this );
		} catch ( er ) {
			return false;
		}
	},

   setCustomData: function( key, value ) {
      var $this = ( typeof this.$node === 'undefined' ) ? this : this.$node;
		var expandoNumber = $this.getUniqueId(),
			dataSlot = customData[ expandoNumber ] || ( customData[ expandoNumber ] = {} );

		dataSlot[ key ] = value;

		return this;
	},

   getCustomData: function( key ) {
      var $this = ( typeof this.$node === 'undefined' ) ? this : this.$node;
		var expandoNumber = $this[ 'data-ved-expando' ],
			dataSlot = expandoNumber && customData[ expandoNumber ];

		return ( dataSlot && key in dataSlot ) ? dataSlot[ key ] : null;
	},

   removeCustomData: function( key ) {
      var $this = ( typeof this.$node === 'undefined' ) ? this : this.$node;
		var expandoNumber = $this[ 'data-ved-expando' ],
			dataSlot = expandoNumber && customData[ expandoNumber ],
			retval, hadKey;

		if ( dataSlot ) {
			retval = dataSlot[ key ];
			hadKey = key in dataSlot;
			delete dataSlot[ key ];
		}

		return hadKey ? retval : null;
	},

   clearCustomData: function() {
      var $this = ( typeof this.$node === 'undefined' ) ? this : this.$node;

		// Clear all event listeners
		this.removeAllListeners();

		var expandoNumber = $this[ 'data-ved-expando' ];
		expandoNumber && delete customData[ expandoNumber ];
	},

   getUniqueId: function() {
      var $this = ( typeof this.$node === 'undefined' ) ? this : this.$node;
		return $this[ 'data-ved-expando' ] || ( $this[ 'data-ved-expando' ] = VED.tools.getNextNumber() );
	}

});

VED.dom.domObject.implement( new Events );

})();

Element.extend( new VED.dom.domObject );


VED.dom.text = new Class();
VED.dom.text.implement( new Element );

VED.dom.text.implement({
   
   initialize: function( text, ownerDocument ) {
      if( typeof text == 'string' )
         text = ( ownerDocument ? ownerDocument : document ).createTextNode( text );
         
      this.$node = text;
   },
   
   type: 3,
   
   getLength: function() {
		return this.$node.nodeValue.length;
	},
   
   getText: function() {
		return this.$node.nodeValue;
	},
   
   setText: function( text ) {
		this.$node.nodeValue = text;
	},
   
   split: function( offset ) {
		// Saved the children count and text length beforehand.
		var parent = this.$node.parentNode,
			count = parent.childNodes.length,
			length = this.getLength();

		var doc = this.getDocument();
		var retval = new VED.dom.text( this.$node.splitText( offset ), doc );

		if ( parent.childNodes.length == count ) {
			// If the offset is after the last char, IE creates the text node
			// on split, but don't include it into the DOM. So, we have to do
			// that manually here.
			if( offset >= length ) {
				retval = doc.createText( '' );
				retval.insertAfter( this );
			} else {
				// IE BUG: IE8+ does not update the childNodes array in DOM after splitText(),
				// we need to make some DOM changes to make it update. (#3436)
				var workaround = doc.createText( '' );
				workaround.insertAfter( retval );
				workaround.remove();
			}
		}

		return retval;
	},
   
   substring: function( indexA, indexB ) {
		// We need the following check due to a Firefox bug
		// https://bugzilla.mozilla.org/show_bug.cgi?id=458886
		if( typeof indexB != 'number' )
			return this.$node.nodeValue.substr( indexA );
		else
			return this.$node.nodeValue.substring( indexA, indexB );
	}
   
});

VED.dom.text.implement( new Element );





function $(el){
	if (!el) return null;
	if (el.htmlElement) return Garbage.collect(el);
	if ([window, document].contains(el)) return el;
	var type = $type(el);
	if (type == 'string'){
		el = document.getElementById(el);
		type = (el) ? 'element' : false;
	}
	if( type == 'textnode' || type == 'whitespace' ) return new VED.dom.text( el ); // !window.ie ? VED.tools.extend(el, Element.prototype) : el; // inDy modified
	else if( type == 'fragment' ) return VED.tools.extend(el, Element.prototype);
	else if (type != 'element') return null;
	if (el.htmlElement) return Garbage.collect(el);
	if (['object', 'embed'].contains(el.tagName.toLowerCase())) return el;
	VED.tools.extend(el, Element.prototype);
	el.htmlElement = function(){};
	return Garbage.collect(el);
};

Window.extend({
   getViewPaneSize: function() {
		var doc = this.document,
			stdMode = doc.compatMode == 'CSS1Compat';
		return {
			width: ( stdMode ? doc.documentElement.clientWidth : doc.body.clientWidth ) || 0,
			height: ( stdMode ? doc.documentElement.clientHeight : doc.body.clientHeight ) || 0
		};
	},
   getScrollPosition: function() {
		if ( 'pageXOffset' in this ) {
			return {
				x: this.pageXOffset || 0,
				y: this.pageYOffset || 0
			};
		} else {
			var doc = this.document;
			return {
				x: doc.documentElement.scrollLeft || doc.body.scrollLeft || 0,
				y: doc.documentElement.scrollTop || doc.body.scrollTop || 0
			};
		}
	},
   getFrame: function() {
		var iframe = this.frameElement;
		return iframe ? $( iframe ) : null;
	}
});




Event.implement({
   getKey: function() {
		return this.event.keyCode || this.event.which;
	},

   getKeystroke: function() {
		var keystroke = this.getKey();

		if( this.event.ctrlKey || this.event.metaKey )
			keystroke += VED.CTRL;

		if( this.event.shiftKey )
			keystroke += VED.SHIFT;

		if( this.event.altKey )
			keystroke += VED.ALT;

		return keystroke;
	},

   getTarget: function() {
		var rawNode = this.event.target || this.event.srcElement;
		return rawNode ? $( rawNode ) : null;
	},

   getPhase: function() {
		return this.event.eventPhase || 2;
	},

   getPageOffset : function() {
		var doc = this.getTarget().getDocument();
		var pageX = this.event.pageX || this.event.clientX + ( doc.documentElement.scrollLeft || doc.body.scrollLeft );
		var pageY = this.event.pageY || this.event.clientY + ( doc.documentElement.scrollTop || doc.body.scrollTop );
		return { x : pageX, y : pageY };
	}

});

VED.CTRL  = 0x110000;
VED.SHIFT = 0x220000;
VED.ALT   = 0x440000;

VED.EVENT_PHASE_CAPTURING = 1;
VED.EVENT_PHASE_AT_TARGET = 2;
VED.EVENT_PHASE_BUBBLING  = 3;





VED.NODE_ELEMENT = 1;
VED.NODE_DOCUMENT = 9;
VED.NODE_TEXT = 3;
VED.NODE_COMMENT = 8;
VED.NODE_DOCUMENT_FRAGMENT = 11;

VED.POSITION_IDENTICAL = 0;
VED.POSITION_DISCONNECTED = 1;
VED.POSITION_FOLLOWING = 2;
VED.POSITION_PRECEDING = 4;
VED.POSITION_IS_CONTAINED = 8;
VED.POSITION_CONTAINS = 16;


*/













function $isBlockBoundary( el,  customNodeNames ) {
   var blockBoundaryDisplayMatch = {
      'block' : 1, 'list-item' : 1, 'table' : 1, 'table-row-group' : 1,
      'table-header-group' : 1, 'table-footer-group' : 1, 'table-row' : 1,
      'table-column-group' : 1, 'table-column' : 1, 'table-cell' : 1, 'table-caption' : 1
   };
   var nodeNameMatches = VED.tools.extend( { hr : 1 }, customNodeNames || {} );
   return blockBoundaryDisplayMatch[ $(el).getStyle( 'display' ) ] || nodeNameMatches[ el.tagName.toLowerCase() ];
}

function $getAscendant( el, name, includeSelf ) {
   if ( !includeSelf )
      el = el.parentNode;

   while( el ) {
      if( el.nodeName && el.nodeName.toLowerCase() == name )
         return $( el );

      el = el.parentNode;

   } // End while

   return null;

}


Element.extend({

   getDocument: function() {
		return ( this.ownerDocument || this.parentNode.ownerDocument );
	},

   isBlockBoundary: function( customNodeNames ) {
      return $isBlockBoundary( this, customNodeNames );
   },

   appendBogus : function() {
      var lastChild = this.getLast();

		// Ignore empty/spaces text.
		while ( lastChild && lastChild.type == VED.NODE_TEXT && !lastChild.textContent.rtrim() )
			lastChild = lastChild.getPrevious();
		if ( !lastChild || !lastChild.is || !lastChild.is( 'br' ) ) {
			var bogus = window.opera ? this.getDocument().createTextNode( '' ) : this.getDocument().createElement( 'br' );
			window.gecko && bogus.setAttribute( 'type', '_moz' );
			this.append( bogus );
		}

   },



   /**
    * Breaks one of the ancestor element in the element position, moving
    * this element between the broken parts.
    * @param {Element} parent The anscestor element to get broken.
    * @example
    * // Before breaking:
    * //     <b>This <i>is some<span /> sample</i> test text</b>
    * // If "element" is <span /> and "parent" is <i>:
    * //     <b>This <i>is some</i><span /><i> sample</i> test text</b>
    * element.breakParent( parent );
    * @example
    * // Before breaking:
    * //     <b>This <i>is some<span /> sample</i> test text</b>
    * // If "element" is <span /> and "parent" is <b>:
    * //     <b>This <i>is some</i></b><span /><b><i> sample</i> test text</b>
    * element.breakParent( parent );
    */
   breakParent : function( parent ) {
      var range = new VED.Range( this.getDocument() );

      // We'll be extracting part of this element, so let's use our
      // range to get the correct piece.
      range.setStartAfter( this );
      range.setEndAfter( parent );

      // Extract it.
      var docFrag = range.extractContents();

      // Move the element outside the broken element.
      range.insertNode( this.remove() );

      // Re-insert the extracted piece after the element.
      this.parentNode.insertBefore( docFrag, this.nextSibling );
   },


   /**
    * Checks if the element name matches one or more names.
    * @param {String} name[,name[,...]] One or more names to be checked.
    * @returns {Boolean} true if the element name matches any of the names.
    * @example
    * var element = new Element( 'span' );
    * alert( <b>element.is( 'span' )</b> );  "true"
    * alert( <b>element.is( 'p', 'span' )</b> );  "true"
    * alert( <b>element.is( 'p' )</b> );  "false"
    * alert( <b>element.is( 'p', 'div' )</b> );  "false"
    */
   is : function() {
      var name = this.getTag();

		if( typeof arguments[ 0 ] == 'object' )
			return !!arguments[ 0 ][ name ];

      for( var i = 0 ; i < arguments.length ; i++ ) {
         if( arguments[ i ] == name )
            return true;
      }
      return false;
   },

   isEditable : function() {
      var name = this.getTag();

      if( this.isReadOnly() || $getComputedStyle( this, 'display' ) == 'none' ||
				 $getComputedStyle( this, 'visibility' ) == 'hidden' ||
				 VED.dtd.$nonEditable[ name ] ||
				 VED.dtd.$empty[ name ] ||
				 ( this.is( 'a' ) &&
					 ( this.data( 'cke-saved-name' ) || this.hasAttribute( 'name' ) ) &&
					 !this.childNodes.length
				 )
      ) {
			return false;
		}

		if( textCursor !== false ) {
			// Get the element DTD (defaults to span for unknown elements).
			var dtd = VED.dtd[ name ] || VED.dtd.span;
			// In the DTD # == text node.
			return !!( dtd && dtd[ '#' ] );
		}

		return true;

   },


   isIdentical: function( otherElement ) {
		// do shallow clones, but with IDs
		var thisEl = this.clone( 0, 1 ),
			otherEl = otherElement.clone( 0, 1 );

		// Remove distractions.
		thisEl.removeAttributes( [ '_moz_dirty', 'data-ved-expando', 'data-ved-saved-href', 'data-ved-saved-name' ] );
		otherEl.removeAttributes( [ '_moz_dirty', 'data-ved-expando', 'data-ved-saved-href', 'data-ved-saved-name' ] );

		// Native comparison available.
		if ( thisEl.$.isEqualNode ) {
			// Styles order matters.
			thisEl.$.style.cssText = VED.tools.normalizeCssText( thisEl.$.style.cssText );
			otherEl.$.style.cssText = VED.tools.normalizeCssText( otherEl.$.style.cssText );
			return thisEl.$.isEqualNode( otherEl.$ );
		} else {
			thisEl = thisEl.getOuterHtml();
			otherEl = otherEl.getOuterHtml();

			// Fix tiny difference between link href in older IEs.
			if ( VED.env.ie && VED.env.version < 9 && this.is( 'a' ) ) {
				var parent = this.getParent();
				if ( parent.type == 1 ) {
					var el = parent.clone();
					el.setHtml( thisEl ), thisEl = el.getHtml();
					el.setHtml( otherEl ), otherEl = el.getHtml();
				}
			}

			return thisEl == otherEl;
		}
	},


   /**
    * Gets the closes ancestor node of a specified node name.
    * @param {String} name Node name of ancestor node.
    * @param {Boolean} includeSelf (Optional) Whether to include the current
    * node in the calculation or not.
    * @returns {node} Ancestor node.
    */
   getAscendant : function( name, includeSelf ) {
      return $getAscendant( this, name, includeSelf );
   },

   hasAscendant : function( name, includeSelf ) {
      var el = this;
      if( !includeSelf )
         el = el.parentNode;

      while( el ) {
         if( el.nodeName && el.nodeName.toLowerCase() == name )
            return true;

         el = el.parentNode;

      } // End while

      return false;

   },

   isReadOnly: function() {
		var element = this;

		if( element && typeof element.isContentEditable != 'undefined' )
			return !( element.isContentEditable || element.data( 'cke-editable' ) );
		else {
			// Degrade for old browsers which don't support "isContentEditable", e.g. FF3
			while( element ) {
				if ( element.data( 'cke-editable' ) )
					break;

				if ( element.getAttribute( 'contentEditable' ) == 'false' )
					return true;
				else if ( element.getAttribute( 'contentEditable' ) == 'true' )
					break;

				element = element.getParent();
			}

			// Reached the root of DOM tree, no editable found.
			return !element;
		}
	},


   data: function( name, value ) {
		name = 'data-' + name;
		if( value === undefined )
			return this.getAttribute( name );
		else if ( value === false )
			this.removeAttribute( name );
		else
			this.setAttribute( name, value );

		return null;
	},


   getHtml: function() {
		var retval = this.innerHTML;
		// Strip <?xml:namespace> tags in IE. (#3341).
		return VED.env.ie ? retval.replace( /<\?[^>]*>/g, '' ) : retval;
	}

});

Element.setMarker = function( database, element, name, value ) {
   !element.getData && addVault( element )
	var id = element.getData( 'list_marker_id' ) ||
			( element.setData( 'list_marker_id', getNextNumber() ).getData( 'list_marker_id' ) ),
		markerNames = element.getData( 'list_marker_names' ) ||
			( element.setData( 'list_marker_names', {} ).getData( 'list_marker_names' ) );
	database[id] = element;
	markerNames[name] = 1;

	return element.setData( name, value );
};



/**
 * Gets the current computed value of one of the element CSS style
 * properties.
 * @function
 * @param {String} propertyName The style property name.
 * @returns {String} The property value.
 * @example
 * var element = new Element( 'span' );
 * alert( <b>element.getComputedStyle( 'display' )</b> );  // "inline"
 */
var $getComputedStyle =
   VED.env.ie ?
      function( el, propertyName ) {
         return el.currentStyle[ VED.tools.cssStyleToDomStyle( propertyName ) ];
      }
   :
      function( el, propertyName ) {
         var doc = el.ownerDocument,
             win = doc.parentWindow || doc.defaultView;
         return win.getComputedStyle( el, '' ).getPropertyValue( propertyName );
      }


var getNextNumber = (function(){
   var last = 0;
   return function() {
      return ++last;
   };
})();

var listNodeNames = { ol : 1, ul : 1 };

var vaultClass = new Class({
   initialize: function() {
      this.ved_expando = getNextNumber();
   }
});

(function(){
   var data = {};

   vaultClass.implement({
      setData: function( key, value ) {
         var dataSlot = data[ this.ved_expando ] || ( data[ this.ved_expando ] = {} );
         dataSlot[ key ] = value;
      },

      getData: function( key ) {
         var dataSlot = this.ved_expando && data[ this.ved_expando ];
         return dataSlot && dataSlot[ key ];
      },

      removeData: function( key ) {
         var dataSlot = this.ved_expando && data[ this.ved_expando ],
             result = dataSlot && dataSlot[ key ];
         if( !defined( result ) )
            delete dataSlot[ key ];

         return result || null;

      }

   });

})();

var addVault = function(obj){
   var vaultObject = new vaultClass();
   VED.tools.extend(obj,vaultObject);
}


